package com.bitejiuyeke.job_publish.service.impl;

import com.bitejiuyeke.job_publish.common.AppResult;
import com.bitejiuyeke.job_publish.common.PageResult;
import com.bitejiuyeke.job_publish.common.ResultCode;
import com.bitejiuyeke.job_publish.dao.JobMapper;
import com.bitejiuyeke.job_publish.enums.DeleteStateEnum;
import com.bitejiuyeke.job_publish.enums.JobStateEnum;
import com.bitejiuyeke.job_publish.exception.ApplicationException;
import com.bitejiuyeke.job_publish.model.Job;
import com.bitejiuyeke.job_publish.model.User;
import com.bitejiuyeke.job_publish.service.IJobService;
import com.bitejiuyeke.job_publish.service.IUserService;
import com.bitejiuyeke.job_publish.utils.JsonUtils;
import com.bitejiuyeke.job_publish.utils.RedisUtils;
import com.bitejiuyeke.job_publish.utils.StringUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @Author 比特就业课
 */
@Slf4j
@Service
public class JobServiceImpl implements IJobService {

    // 有效时间 60 分钟
    private static final int EFFECTIVE_TIME = 60 * 60;

    private static final String KEY_CODE_PREFIX = "KEY_JOB:ID:";

    @Resource
    private RedisUtils redisUtils;
    @Resource
    private JobMapper mapper;
    @Resource
    private IUserService userService;

    @Override
    public void create(Job job) {
        // 校验
        checkForCreate(job);
        // 默认值
        job.setDeleteState((byte) DeleteStateEnum.NORMAL.getCode()); // 删除状态
        job.setFavoriteCount(0); // 收藏数量
        job.setReceiveCount(0); // 访问数量
        job.setVisitCount(0); // 访问数量
        // 时间
        Date now = new Date();
        // 过期天数
        if (job.getTimeLimit() > 0) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(now);
            // 累加
            calendar.add(Calendar.DAY_OF_YEAR, job.getTimeLimit());
            // 设置
            job.setExpires(calendar.getTime());
        } else {
            // 设置永不过期
            job.setExpires(null);
        }
        job.setCreateTime(now);
        job.setUpdateTime(now);
        // 写入数据库
        int row = mapper.insert(job);
        if (row != 1) {
            log.info("新增职位失败. " + AppResult.failed(ResultCode.FAILED_CREATE));
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_CREATE));
        }
    }

    private void checkForCreate(Job job) {
        // 校验标识
        boolean checkFlag = true;
        // 对象是否为空
        if (job == null) {
            checkFlag = false;
        }
        // 发布者
        if (job.getUserId() == null || job.getUserId() <= 0) {
            checkFlag = false;
        }
        // 标题
        if (StringUtils.isEmpty(job.getTitle())) {
            checkFlag = false;
        }
        // 职位描述
        if (StringUtils.isEmpty(job.getDescription())) {
            checkFlag = false;
        }
        // 奖金
        if (job.getRewardUpper() == null || job.getRewardUpper() < 0) {
            checkFlag = false;
        }
        if (job.getRewardLower() == null || job.getRewardLower() < 0) {
            checkFlag = false;
        }
        // 工期
        if (job.getTimeLimit() == null || job.getTimeLimit() < 0) {
            checkFlag = false;
        }
        // 状态
        if (job.getState() == null || JobStateEnum.valueOf(job.getState()) == null) {
            checkFlag = false;
        }
        // 校验不通抛出异常
        if (!checkFlag) {
            log.info("新增职位失败. " + ResultCode.FAILED_PARAMS_VALIDATE);
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
    }

    @Override
    public void deleteById(Long id, Long userId) {
        // 校验
        if (id == null || id <= 0) {
            log.info("删除职位失败. " + AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        // 校验职位是否存在
        Job existJob = selectById(id);
        if (existJob == null) {
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_NOT_EXISTS));
        }
        // 校验是否自己发布的职位
        if (existJob.getUserId() != userId) {
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_NOT_PERMISSION));
        }
        // 删除时并不真正删除数据库中的记录，而是把删除标识置为删除状态
        Job updateJob = new Job();
        updateJob.setId(id);
        updateJob.setDeleteState((byte) DeleteStateEnum.DELETED.getCode());
        updateJob.setUpdateTime(new Date());
        // 更新数据库
        mapper.updateByPrimaryKeySelective(updateJob);
        // 删除缓存
        redisUtils.del(buildKey(id));

    }

    @Override
    public void modifyState(Long id, JobStateEnum stateEnum, Long userId) {
        // 校验
        if (id == null || id <= 0 || stateEnum == null) {
            log.info(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        // 校验职位是否存在
        Job existJob = selectById(id);
        if (existJob == null) {
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_NOT_EXISTS));
        }
        // 校验是否自己发布的职位
        if (existJob.getUserId() != userId) {
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_NOT_PERMISSION));
        }
        // 删除时并不真正删除数据库中的记录，而是把删除标识置为删除状态
        Job updateJob = new Job();
        updateJob.setId(id);
        updateJob.setState((byte) stateEnum.getCode());
        updateJob.setUpdateTime(new Date());
        // 更新数据库
        mapper.updateByPrimaryKeySelective(updateJob);
        // 更新缓存
        existJob.setState((byte) stateEnum.getCode());
        setToCache(existJob);
    }

    @Override
    public void modify(Job job) {
        // 校验
        if (job == null || job.getId() == null || job.getId() <= 0
                || job.getUserId() == null || job.getUserId() <= 0) {
            log.info(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        // 更新对象
        Job updateJob = new Job();
        updateJob.setId(job.getId());
        updateJob.setUserId(job.getUserId());
        // 校验
        boolean bool = checkForModify(job, updateJob);
        if (!bool) {
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        // 更新时间
        updateJob.setUpdateTime(new Date());
        // 校验职位是否存在
        Job exitsJob = mapper.selectByPrimaryKey(job.getId());
        if (exitsJob == null) {
            log.info("职位不存在. " + ResultCode.FAILED_NOT_EXISTS);
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_NOT_EXISTS));
        }
        // 校验是否发布者
        if (exitsJob.getUserId() != job.getUserId()) {
            log.info(ResultCode.FAILED_NOT_PERMISSION.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_NOT_PERMISSION));
        }
        // 标题
        if (!StringUtils.isEmpty(job.getTitle())) {
            updateJob.setTitle(job.getTitle());
        }
        // 最低价
        if (job.getRewardLower() != null) {
            updateJob.setRewardLower(job.getRewardLower());
        }
        // 最高价
        if (job.getRewardUpper() != null) {
            updateJob.setRewardUpper(job.getRewardUpper());
        }
        // 过期日
        if (job.getTimeLimit() != null) {
            // 有效天数
            updateJob.setTimeLimit(job.getTimeLimit());
            // 有期日
            if (job.getTimeLimit() > 0) {
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(exitsJob.getCreateTime());
                // 累加
                calendar.add(Calendar.DAY_OF_YEAR, job.getTimeLimit());
                // 设置
                updateJob.setExpires(calendar.getTime());
            } else {
                // 设置永不过期
                updateJob.setExpires(null);
            }
        }
        // 描述
        if (!StringUtils.isEmpty(job.getDescription())) {
            updateJob.setDescription(job.getDescription());
        }
        // 更新数据库
        int row = mapper.updateByPrimaryKeySelective(updateJob);
        if (row != 1) {
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED));
        }
        // 删除缓存
        redisUtils.del(buildKey(job.getId()));

    }

    // 校验并为更新对象赋值
    private boolean checkForModify (Job job, Job updateJob) {

        // 校验标识
        boolean checkFlag = false;
        // 标题
        if (!StringUtils.isEmpty(job.getTitle())) {
            updateJob.setTitle(job.getTitle());
            checkFlag = true;
        }
        // 职位描述
        if (!StringUtils.isEmpty(job.getDescription())) {
            updateJob.setDescription(job.getDescription());
            checkFlag = true;
        }
        // 奖金上限
        if (job.getRewardUpper() != null && job.getRewardUpper() > 0) {
            updateJob.setRewardUpper(job.getRewardUpper());
            checkFlag = true;
        }
        // 奖金下限
        if (job.getRewardLower() != null && job.getRewardLower() > 0) {
            updateJob.setRewardLower(job.getRewardLower());
            checkFlag = true;
        }
        // 工期
        if (job.getTimeLimit() != null && job.getTimeLimit() > 0) {
            updateJob.setTimeLimit(job.getTimeLimit());
            checkFlag = true;
        }
        // 过期时间
        if (job.getExpires() != null) {
            updateJob.setExpires(job.getExpires());
            checkFlag = true;
        }
        return checkFlag;
    }

    @Override
    public Job selectById(Long id) {
        // 参数校验
        if (id == null || id <= 0) {
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        // 从缓存中获取
        Job job = getFromCache(id);
        if (job != null) {
            // 直接返回
            return job;
        }
        // 从数据库中查询
        job = selectByIdFromDB(id);
        if (job == null || job.getDeleteState() == DeleteStateEnum.DELETED.getCode()) {
            return null;
        }
        // 设置发布者
        User publisher = userService.selectById(job.getUserId());
        if (publisher == null) {
            return null;
        }
        job.setPublisher(publisher);
        // 设置到缓存
        setToCache(job);
        // 返回结果
        return job;
    }

    @Override
    public void addFavoriteCount(Long id, Integer count) {
        if (id == null || id <= 0 || count == null || count <= 0) {
            log.info("增加收藏数失败. " + ResultCode.FAILED_PARAMS_VALIDATE.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        // 获取Job对象
        Job job = selectById(id);
        if (job == null) {
            log.info("增加收藏数失败. " + ResultCode.FAILED_NOT_EXISTS);
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_NOT_EXISTS));
        }
        // 更新对象
        Job updateJob = new Job();
        updateJob.setId(id);
        updateJob.setFavoriteCount(job.getFavoriteCount() + count);
        int row = mapper.updateByPrimaryKeySelective(updateJob);
        if (row != 1) {
            log.info("增加收藏数失败. " + ResultCode.FAILED);
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED));
        }
        // 更新缓存
        job.setFavoriteCount(job.getFavoriteCount() + count);
        setToCache(job);
    }

    @Override
    public void minusFavoriteCount(Long id, Integer count) {
        if (id == null || id <= 0 || count == null || count <= 0) {
            log.info("减少收藏数失败. " + ResultCode.FAILED_PARAMS_VALIDATE.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        // 获取Job对象
        Job job = selectById(id);
        if (job == null) {
            log.info("增加收藏数失败. " + ResultCode.FAILED_NOT_EXISTS);
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_NOT_EXISTS));
        }
        // 更新对象
        Job updateJob = new Job();
        updateJob.setId(id);
        int favoriteCount = job.getFavoriteCount() - count < 0 ? 0 : job.getFavoriteCount() - count;
        updateJob.setFavoriteCount(favoriteCount);
        updateJob.setUpdateTime(new Date());
        int row = mapper.updateByPrimaryKeySelective(updateJob);
        if (row != 1) {
            log.info("增加收藏数失败. " + ResultCode.FAILED);
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED));
        }
        // 更新缓存
        job.setFavoriteCount(favoriteCount);
        setToCache(job);
    }

    @Override
    public void addReceiveCount(Long id, Integer count) {
        if (id == null || id <= 0 || count == null || count <= 0) {
            log.info("增加接收简历数失败. " + ResultCode.FAILED_PARAMS_VALIDATE.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        // 获取Job对象
        Job job = selectById(id);
        if (job == null) {
            log.info("增加收藏数失败. " + ResultCode.FAILED_NOT_EXISTS);
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_NOT_EXISTS));
        }
        // 更新对象
        Job updateJob = new Job();
        updateJob.setId(id);
        updateJob.setReceiveCount(job.getReceiveCount() + count);
        int row = mapper.updateByPrimaryKeySelective(updateJob);
        if (row != 1) {
            log.info("增加收藏数失败. " + ResultCode.FAILED);
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED));
        }
        // 更新缓存
        job.setReceiveCount(job.getReceiveCount() + count);
        setToCache(job);
    }

    @Override
    public void addVisitCount(Long id, Integer count) {
        if (id == null || id <= 0 || count == null || count <= 0) {
            log.info("增加访问数失败. " + ResultCode.FAILED_PARAMS_VALIDATE.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        // 获取Job对象
        Job job = selectById(id);
        if (job == null) {
            log.info("增加收藏数失败. " + ResultCode.FAILED_NOT_EXISTS);
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_NOT_EXISTS));
        }
        // 更新对象
        Job updateJob = new Job();
        updateJob.setId(id);
        updateJob.setVisitCount(job.getVisitCount() + count);
        int row = mapper.updateByPrimaryKeySelective(updateJob);
        if (row != 1) {
            log.info("增加收藏数失败. " + ResultCode.FAILED);
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED));
        }
        // 更新缓存
        job.setVisitCount(job.getVisitCount() + count);
        setToCache(job);
    }

    @Override
    public int totalCount(Job record) {
        if (record == null || record.getPageSize() == null || record.getOffset() == null) {
            log.info("获取首页职位总数失败. " + ResultCode.FAILED_PARAMS_VALIDATE);
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        // 查询总记录数
        int totalCount = mapper.totalCount(record);
        return totalCount;
    }

    @Override
    public PageResult<Job> selectByPage(Job record) {
        // 查询总记录数
        int totalRecord = totalCount(record);
        // 分页结果对象
        PageResult<Job> pageResult = new PageResult<>(record.getPageNum(), record.getPageSize(), totalRecord);
        // 分页记录列表
        List<Job> list = mapper.selectByPage(record);
        // 设置结果
        pageResult.setRows(list);
        // 返回结果
        return pageResult;
    }

    @Override
    public int totalCountByUser(Job record) {
        if (record == null || record.getPageSize() == null || record.getOffset() == null || record.getUserId() == null) {
            log.info("根据用户条件获取记录总数失败. " + ResultCode.FAILED_PARAMS_VALIDATE);
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        // 查询总记录数
        int totalCount = mapper.totalCountByUser(record);
        return totalCount;
    }

    @Override
    public PageResult<Job> selectPageByUser(Job record) {
        // 查询总记录数
        int totalRecord = totalCountByUser(record);
        // 分页结果对象
        PageResult<Job> pageResult = new PageResult<>(record.getPageNum(), record.getPageSize(), totalRecord);
        // 分页记录列表
        List<Job> list = mapper.selectPageByUser(record);
        // 设置结果
        pageResult.setRows(list);
        // 返回结果
        return pageResult;
    }

    private Job selectByIdFromDB(Long id) {
        if (id == null || id < 0) {
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        // 查询职位信息
        Job job = mapper.selectByPrimaryKey(id);
        return job;
    }

    // ============ 缓存 ============
    // 构建Key
    private String buildKey(Long id) {
        return KEY_CODE_PREFIX + id;
    }

    // 从缓存中获取对象
    private Job getFromCache(Long id) {
        String content = (String) redisUtils.get(buildKey(id));
        if (StringUtils.isEmpty(content)) {
            // 缓存中不存在
            return null;
        }
        // 转换为对象
        Job job = JsonUtils.readValue(content, Job.class);
        return job;
    }

    // 设置对象到缓存
    private void setToCache (Job job) {
        if (job == null || job.getId() == null) {
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        // 写入缓存
        redisUtils.set(buildKey(job.getId()), JsonUtils.writeValueAsString(job), EFFECTIVE_TIME);
    }
}
